import UIKit
//构造过程是为了使用类、结构体或枚举类型的实例而进行的准备过程。这个过程包含为实例每个属性设置初始值和准备必要的初始化任务。通过定义构造器来实现构造过程

//最简单的构造器是不带任何参数的实例方法，以init命名
struct Fahrentit {
    var temperature : Double
    init() {
        temperature = 32.0
    }
}

var f = Fahrentit()
f.temperature

//属性默认值。在构造器中为存储型属性设置初始值；也可以在属性声明时为其设置初始值
struct Fahrentit2 {
    var tempearture = 32.0
    init() {
        
    }
}

let fa2 = Fahrentit2()
fa2.tempearture

//定制化构造过程。
//构造参数
struct Celsius {
    var tempeartureInCelsis:Double = 0.0
    init(fromFahrenit fahrenit: Double) {
        tempeartureInCelsis = (fahrenit - 32.0) / 1.8
    }
    
    init(fromKelvin kelvin: Double) {
        tempeartureInCelsis = kelvin - 273.15
    }

}

let boilingPointOfWater = Celsius(fromFahrenit: 212.0)
let freezingPointoFWater = Celsius(fromKelvin: 273.15)
boilingPointOfWater.tempeartureInCelsis
freezingPointoFWater.tempeartureInCelsis

//内部和外部参数。跟函数和方法相同，构造参数也存在一个在构造器内部使用的参数名称和一个在调用构造器时使用的外部参数名称。
struct Color {
    var red = 0.0, green = 0.0, blue = 0.0
    init(red:Double, green: Double,blue:Double) {
        self.red = red
        self.green = green
        self.blue = blue
    }
}

let megenta = Color(red: 1.0, green: 0.0, blue: 1.0)
//可选属性类型.如果你定制类型包含一个逻辑上允许取值为空的存储属性。你都应定义他们为可选类型。可选类型自动初始化为nil.
class SurveyQuestion {
    var text: String
    var response: String?
    init(text: String) {
        self.text = text
    }
    
    func ask() {
        print(text)
    }
}

let cheeseQuestion = SurveyQuestion(text: "do you like cheese?")
cheeseQuestion.ask()
cheeseQuestion.response = "Yes"
//构造过程中常量属性的修改 上面var text: String 中 var -》 let,只要在构造过程结束前常量能确定，可以在构造过程中任意时间点修改常量属性的值。
//默认构造器。swift默认提供一个自身没有定义任何构造器的结构体和基类。这个默认的构造器简单的创建一个所有属性值都设置为默认值的实例。

class ShoppingListItem{
    var name: String?
    var quantity = 1
    var purchased = false
}
var item = ShoppingListItem() //由于shoppinglistitem类中的所有属性都有默认值，且它是没有父类的基类，它将自动获得一个可以为所有属性设置默认值的默认构造器。

//结构体的逐一成员构造器。除了上面提到的默认构造器，如果结构体对所有存储型属性提供了默认自身没有提供定制的构造器，他们都能自动获取一个逐一成员构造器
struct Size {
    var width = 0.0, height = 0.0
}

let twoByTwo = Size(width: 2.0, height: 2.0)//由于这两个存储型属性都有默认值。结构体Size自动获得了一个逐一成员构造器。init(width:height:)

//值类型的构造器代理。构造器可以通过调用其他的构造器来完成实例的部分构造过程。称为构造器代理。它能减少多个构造器的代码重复。
struct Point {
    var x = 0.0, y = 0.0
}

struct Rect {
    var oirgin = Point()
    var size = Size()
    init() {}
    init(origin: Point, size: Size) {
        self.oirgin = origin
        self.size = size
    }
    init (center:Point, size: Size) {
        let originX = center.x - size.width / 2
        let originY = center.y - size.height / 2
        self.init(origin: Point(x:originX , y: originY), size: size)
    }
}

let basicRect = Rect()
let originRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0))
let centerRect = Rect(center: Point(x: 4.0, y:4.0), size: Size(width: 3.0, height: 3.0))

//类的继承和构造过
//指定构造器和构造过程。指定构造器是类中最最重要的构造器。每个类必须还要有一个指定构造器，便利构造器是类中比较次要的，辅助性的构造器。
//构造器链.1.规则1 指定构造器必须调用其直接父类的指定构造器 2.便利构造器必须调用同一类中定义的其他构造器。3.便利构造器必须最终以调用一个指定构造器结束。

//简单记忆。
//****指定构造器必须总是向上代理  便利构造器必须总是横向代理。***

//指定构造器和便利构造器实战
class Food {
    var name:String
    init(name: String) {
        self.name = name
    }
    convenience init() {
        self.init(name: "unnamed")
    }
}

let food = Food(name: "add")
food.name
let food3 = Food()
food3.name


class  RecipeIngredient: Food {
    var quantity: Int

    init(name:String, quantity: Int) {
        self.quantity = quantity
        super.init(name: name)
    }
    convenience override init(name: String) {
        self.init(name: name, quantity: 1)
    }
}

let recip = RecipeIngredient()
recip.name
recip.quantity

let oneBacon = RecipeIngredient(name: "bacon")
oneBacon.name
oneBacon.quantity

let sixEgges = RecipeIngredient(name: "Egges", quantity: 6)
sixEgges.name
sixEgges.quantity

class ShoppingListItem1 : RecipeIngredient
{
    var purchased = false
    var description : String  {
        var output = "\(quantity) *\(name.lowercased())"

        output += purchased ? "对 " : "错 "
        return output
    }
}

var breakfastList = [
    ShoppingListItem1(),
    ShoppingListItem1(name: "bacon"),
    ShoppingListItem1(name: "eggs", quantity: 6)
]

breakfastList[0].name = "Orange Juice"
breakfastList[0].purchased = true

for item in breakfastList {
    print(item.description)
}

//通过闭包和函数来设置属性的默认值
class SomeClass {
    var tempValue = 0
    let someProperty: String = {
        return "abc"
    }()
    
    var anotherProperty: Int {
        get {
            return tempValue
        }
        
        set(newValue) {
          tempValue = newValue
        }
    }
}

let cls = SomeClass()
cls.anotherProperty
cls.tempValue

cls.anotherProperty = 100
cls.tempValue









